# handle_search_location.py - Handle queue requests to google local search .
# Copyright 2010 Nick Renny <NickRenny@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import datastore
import datetime
import logging
import simplejson as json
import terms
import traceback
import twitter
import tweet
import yaml
import random
import post_data

from dgrWalking import dgrWalking
from google.appengine.api import urlfetch 
from googlemaps import GoogleMaps
from google.appengine.ext import db
import wsgiref.handlers
from google.appengine.runtime import DeadlineExceededError
from google.appengine.ext import webapp

try:
    from google.appengine.api.taskqueue import Task
except:
    from google.appengine.api.labs.taskqueue import Task

#Constant declaration
SMP_NEW_DESTINATION = 100  #for saveMapPoint indicates a new destination was saved
SMP_NO_NEW_DESTINATION = 500 #for saveMapPoint indicates destination same as current location was saved
    
    
class LocationSearchWorker(webapp.RequestHandler):
    def queue_task(self, queue, handler_url, paramdict):
        '''Queue a task that goes to posterous'''
        task = Task(url=handler_url, method='POST', params=paramdict)
        task.add(queue)

    def post(self):
        self.NewDestinationToPost = None
        dgr_yaml_path = self.request.get('dgr-yaml-path')
        yaml_stream = file (dgr_yaml_path, 'r')
        config = yaml.safe_load (yaml_stream)
        dgr_run_time_string = self.request.get('dgr-run-time')
        dgr_run_time = datetime.datetime.\
            fromtimestamp(float(dgr_run_time_string))
        #now set up google local search api call
        
        logging.debug("handle walking ")
        self.config_path = self.request.get('config-path')
        self.twitter_username = config["twitter_username"]
        self.twitter_password = config["twitter_password"]
        
        emotion_json = self.request.get('emotions')
        emotions = json.loads(emotion_json)
        logging.debug("emotions are " .join(emotions))
        #self.walking = dgrWalking(self.config_path)
        
        if(dgr_yaml_path):
            try:
                located = self.walk(emotions)
                if (self.NewDestinationToPost):
                    logging.info('location search ' + dgr_yaml_path + ' ' + \
                                     str(emotions)) 
                    
                    if (located):
                        location_post_data = self.walking.postLocation()
                        logging.debug(location_post_data)
                        dgr_task = Task(url='/post-broadcast', method='POST',
                                        params={'dgr-yaml-path': dgr_yaml_path,
                                                'emotions': emotion_json,
                                                'post-data': location_post_data.as_json()})
                        dgr_task.add('broadcast-queue')
                        logging.info('Success -> ' + str(location_post_data.title))
                    else:
                        logging.info('No location')
            except Exception, e:
                logging.error(type(e))
                logging.error(e)
                logging.error(traceback.format_exc())


            except DeadlineExceededError, exc:
                # Re-throw the exception, returning an HTTP 500 result
                # This will result in this task being called again soon
                raise exc
            except Exception, e:
                logging.error(type(e))
                logging.error(e)
                logging.error(traceback.format_exc())
                # Re-throw the exception so we get called again soon
                raise e
        else:
            logging.debug("No New Destination to Post - not posting")
                
    def walk(self, searchTerms):
        #uses the dgrWalking class to manage setting locations
        #dgrWalking will use the Yaml file plus the tweet search terms to obtain searchTerms to be used to walk
        #or it will use the routine if there is one.
        
        #we should determine based on time of day whether we should be going anywhere
        
        #instantiate dgrWalking class
        logging.debug("instantiate dgrWalking " + self.config_path)
        self.walking = dgrWalking(self.config_path)
        
        #check user exists in our list - if not add the user to the datastore        
        self.walking.addTUser(self.twitter_username, self.twitter_password)
        
        destinations = self.walking.walk(searchTerms)
        #getDestination - returns dict of destinations from google local search
        #destinations = dgrWalking.getDestination()
        logging.debug ('destination type = ' + type(destinations).__name__)
        
        if (type(destinations) is str):           
            #get the right address - home or work
            address = []
            address = self.walking.getAddress(str(self.walking.isHomeOrWork()))
            logging.debug ('we have ' + str(len(address)) + ' adresses' + str(address[0]))
            
            fulladdress = ''
            for addressline in address[0]['addressLines']:
                fulladdress = fulladdress + addressline + ' '
            self.populateUserLocation(address[0]['streetAddress'], address[0]['titleNoFormatting'], address[0]['region'], address[0]['city'], address[0]['lat'], address[0]['lng'], '%s&reviews=1' % address[0]['url'], fulladdress)

            
        elif (isinstance(destinations, list)):
            logging.info (str(len(destinations)))
            logging.info ("destinations = " + str(destinations))
            if (destinations):
                # Get the first destination
                #will need to think about distance/time to arrive - but do that later.
    			
                #set up destination data
                fulladdress = ''
                for addressline in destinations[0]['addressLines']:
                    fulladdress = fulladdress + addressline + ' '
                logging.debug("pop user location")
                self.populateUserLocation(destinations[0]['streetAddress'], destinations[0]['titleNoFormatting'], destinations[0]['region'], destinations[0]['city'], destinations[0]['lat'], destinations[0]['lng'], '%s&reviews=1' % destinations[0]['url'], fulladdress)
            

        else:
            #get the right address - home or work
            logging.debug('destinations from saved map point')
            #address = []
            #address = self.walking.getAddress(str(self.walking.isHomeOrWork()))
            
            self.populateUserLocation(destinations.street_address, destinations.title, destinations.region, destinations.city, destinations.lat, destinations.lng, destinations.url, destinations.address_lines)
        return "True"
        
    def populateUserLocation(self, street_address, title, region, city, lat, lng, url, fulladdress):
        #set up destination data
        logging.debug ('pop usr loc destination type = ' + fulladdress)
        zoom_level = 0
        #street_address = destinations[0]['streetAddress']
        #title = destinations[0]['titleNoFormatting']
        #region = destinations[0]['region']
        #city = destinations[0]['city']
        #lat = destinations[0]['lat']
        #lng = destinations[0]['lng']
        #url = '%s&reviews=1' % destinations[0]['url']
        #phone = ''
            
        #addresslines = '' .join(destinations[0]['addressLines'])
        
        #fulladdress = ''
        #for addressline in destinations[0]['addressLines']:
        #    fulladdress = fulladdress + addressline + ' '
                    
        logging.info ('lat = ' + str(lng))
        logging.info ("Destination: " + fulladdress)
        phone = ''
        self.located = url
        #in Save Destination we need to check that the next destination isn't the same place we are already in. Need to set up return values to indicate this.
        SaveResult = self.walking.SaveDestination(lat, lng, title, url, street_address, region, city, '1', phone, fulladdress)
        logging.debug(SaveResult)
        if (SaveResult == SMP_NO_NEW_DESTINATION):
            self.NewDestinationToPost = None
            
        else:
            self.NewDestinationToPost = 1
    
def main():
    wsgiref.handlers.CGIHandler().run(webapp.WSGIApplication([
                ('/search-location', LocationSearchWorker)], debug=True))
    
if __name__ == '__main__':
    logging.getLogger().setLevel(logging.DEBUG)
    main()
